package net.qiqbframework.loadhanding;

import net.qiqbframework.common.Priority;
import net.qiqbframework.common.utils.AnnotationUtil;
import net.qiqbframework.messaging.Message;
import net.qiqbframework.messaging.annotation.HandlerParameterResolver;
import net.qiqbframework.messaging.annotation.HandlerParameterResolverFactory;

import java.lang.reflect.Executable;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 批量加载参数解析
 */
@Priority(Priority.HIGH)
public class LoadPayloadParameterResolverFactory implements HandlerParameterResolverFactory {
    @Override
    public HandlerParameterResolver<?> createInstance(Executable executable, Parameter[] parameters, int parameterIndex) {
        Class<?> parameterType = parameters[parameterIndex].getType();

        if (parameterIndex == 0 && parameterType.isAssignableFrom(Collection.class)) {
            boolean supportBatch = (boolean) AnnotationUtil.findAnnotationAttributes(executable, LoadHandler.class)
                    .map(attr -> attr.get("supportBatch"))
                    .orElse(false);
            //
            if (supportBatch) {

                return new BatchLoadParameterResolver();
            }
        }
        return null;
    }

    public static class BatchLoadParameterResolver implements HandlerParameterResolver<Object> {

        @Override
        public Object resolveParameter(Message<?> message) {
            if (message instanceof LoadMessage<?, ?> loadMessage) {
                List<Object> bizIdentifierParams = new ArrayList<>();
                findNext(loadMessage, bizIdentifierParams);
                return bizIdentifierParams;
            }
            return null;
        }

        private void findNext(LoadMessage<?, ?> loadMessage, List<Object> bizIdentifierParams) {
            if (loadMessage == null) {
                return;
            }
            bizIdentifierParams.add(loadMessage.getPayload());
            findNext(loadMessage.next(), bizIdentifierParams);
        }

        @Override
        public boolean support(Message<?> message) {
            return message instanceof LoadMessage<?, ?>;
        }

        @Override
        public Class<?> supportedPayloadType() {
            return Collection.class;
        }
    }

}
